package com.szwistar.common.comm.jsonrpc;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.szwistar.common.datastruct.JsonMapper;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * JsonRpc 消息
 * <p>此消息在 JSON 解析时，要根据 msgType 来判断是哪种类型
 */
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property="msgType", visible=false)
@JsonSubTypes({
	@JsonSubTypes.Type(name = "0", value = JsonRpcMessagePing.class),
	@JsonSubTypes.Type(name = "1", value = JsonRpcMessagePingAck.class),
	@JsonSubTypes.Type(name = "10", value = JsonRpcMessageCall.class),
	@JsonSubTypes.Type(name = "20", value = JsonRpcMessageReturn.class),
	@JsonSubTypes.Type(name = "30", value = JsonRpcMessageNotify.class)
})
public abstract class JsonRpcMessage {
	protected static final Logger LOG = LoggerFactory.getLogger(JsonRpcMessage.class);

	// 消息类型
	public static final int MSG_PING = 0;		// PING 消息，用于 keep-alive 和检测连接时延
	public static final int MSG_PING_ACK = 1;	// 是对 PING 消息的应答
	public static final int MSG_CALL = 10;		// 功能调用，相当于向对方发起远程过程调用，包括函数名和参数等；收到此消息的一方应发回 MSG_RETURN 消息。
	public static final int MSG_RETURN = 20;	// 是功能调用 MSG_CALL 的返回消息，里面有调用的返回值，或出错时的错误信息(应先通过 errCode 判断）
	public static final int MSG_NOTIFY = 30;	// 消息通知：一方向另一方的单向通知消息，不需要另一方的应答。

	// 接收/发送 此消息的 JsonRpc 端点
	// 不用于消息的远程传输，仅在本地使用(JsonRpc 实现层用于消息的路由、订阅、统计？)
	protected JsonRpcEndpoint endpoint;
	@JsonIgnore public JsonRpcEndpoint getEndpoint() { return endpoint; }
	@JsonIgnore public void setEndpoint(JsonRpcEndpoint endpoint) { this.endpoint = endpoint; }

	// 消息类型
	protected int msgType;
	@JsonIgnore	// propery visible=false不起作用？！导致JSON编码时会有2个msgType，所把这个忽略掉！！！
	public int getMsgType() { return msgType; }
	public void setMsgType(int msgType) { this.msgType = msgType; }

	// 消息ID：每条消息都一个ID（可用随机数实现，保证在短时间内不会重复），用于避免重复发送，且有利于调试和追溯
	protected long msgId = 0;
	public long getMsgId() { return msgId; }
	public void setMsgId(long msgId) { this.msgId = msgId; }

	protected JsonRpcMessage() {
		super();
	}

	protected JsonRpcMessage(int msgType, long msgId) {
		this();
		this.msgType = msgType;
		this.msgId = msgId;
	}

	@SuppressWarnings("unused")
	public static void main(String[] args) throws Exception {
		JsonRpcMessage msg = JsonRpcMessageReturn.ok(null, 123);
		String json = JsonMapper.toJson(msg);
		System.out.println(json);
		JsonRpcMessage msg2 = JsonMapper.fromJson(json, JsonRpcMessage.class);
	}
}
